﻿Imports WiremetModel.Entities.SupplyOrders
Imports WiremetModel.Entities.OEM
Imports InputValidation
Imports InputValidation.GeneralRules
Imports InputValidation.GeneralRules.NumericInputRules
Imports System.ComponentModel

Public Class WireOrderLineInputDialog

    Private _unitOfWork As UnitOfWork

    Private _wireOrderLine As WireOrderLine
    Public Property WireOrderLine() As WireOrderLine
        Get
            Return _wireOrderLine
        End Get
        Set(ByVal value As WireOrderLine)
            _wireOrderLine = value
        End Set
    End Property

    Private _inputValidator As InputValidator

    Public Sub New(ByRef unitOfWork As UnitOfWork)
        InitializeComponent()
        '_unitOfWork = New UnitOfWork()
        _unitOfWork = unitOfWork
        _wireOrderLine = New WireOrderLine()
        RefreshViewData()
        _inputValidator = New InputValidator()
        ClearErrorLabels()
    End Sub


    Public Sub New(ByRef unitOfWork As UnitOfWork, ByVal wireOrderLine As WireOrderLine)
        Me.New(unitOfWork)

        tb_Diameter.Text = wireOrderLine.Diameter.ToString()
        tb_DiameterToleranceMinus.Text = wireOrderLine.DiameterToleranceMinus.ToString()
        tb_DiameterTolerancePlus.Text = wireOrderLine.DiameterTolerancePlus.ToString()
        tb_EnduranceMax.Text = wireOrderLine.EnduranceMax.ToString()
        tb_EnduranceMin.Text = wireOrderLine.EnduranceMin.ToString()
        tb_Quantity.Text = wireOrderLine.Quantity.ToString()
        tb_UnitPrice.Text = wireOrderLine.UnitPrice().ToString()

        cmb_MaterialGrade.SelectedItem = wireOrderLine.MaterialGrade
        cmb_MeasureUnit.SelectedItem = wireOrderLine.MeasureUnit
        cmb_Packaging.SelectedItem = If(IsNothing(wireOrderLine.Packaging), Nothing, wireOrderLine.Packaging)

        _wireOrderLine = wireOrderLine
    End Sub


    'Private Sub WireOrderLineInputDialog_FormClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs) Handles Me.FormClosed
    '    _unitOfWork.Dispose()
    'End Sub

    Private Sub ClearErrorLabels()
        lbl_MaterialGradeError.Text = String.Empty
        lbl_DiameterError.Text = String.Empty
        lbl_DiameterToleranceMinusError.Text = String.Empty
        lbl_DiameterTolerancePlusError.Text = String.Empty
        lbl_EnduranceMaxError.Text = String.Empty
        lbl_EnduranceMinError.Text = String.Empty
        lbl_MeasureUnitError.Text = String.Empty
        lbl_PackagingError.Text = String.Empty
        lbl_QuantityError.Text = String.Empty
        lbl_UnitPriceError.Text = String.Empty
    End Sub

    Private Sub RefreshViewData()

        Dim materialGradeRepository As New Repository(Of Gatunek)(_unitOfWork)
        Dim measureUnitRepository As New Repository(Of JednostkaMiary)(_unitOfWork)
        Dim packagingRepository As New Repository(Of Pakowanie)(_unitOfWork)

        Dim materialGradeList As IEnumerable(Of Gatunek) = materialGradeRepository.GetAll()
        Dim measureUnitList As IEnumerable(Of JednostkaMiary) = measureUnitRepository.GetAll()
        Dim packagingList As IEnumerable(Of Pakowanie) = packagingRepository.GetAll()

        InitializeComboBox(cmb_MaterialGrade, materialGradeList)
        InitializeComboBox(cmb_MeasureUnit, measureUnitList)
        InitializeComboBox(cmb_Packaging, packagingList)

    End Sub


    Private Sub InitializeComboBox(ByRef inputComboBox As ComboBox, ByVal data As IEnumerable(Of Object))
        inputComboBox.DataSource = New BindingSource(data, Nothing)
        inputComboBox.AutoCompleteCustomSource.Clear()
        inputComboBox.AutoCompleteCustomSource.AddRange(data.Select(Function(x) x.ToString()).ToArray())
        inputComboBox.SelectedIndex = -1
    End Sub


    Private Function GetTotalCost() As Decimal
        If IsNumeric(tb_Quantity.Text.Trim()) AndAlso IsNumeric(tb_UnitPrice.Text.Trim()) Then
            Return Math.Round(Decimal.Parse(tb_Quantity.Text.Trim()) * Decimal.Parse(tb_UnitPrice.Text.Trim()), 2)
        Else
            Return 0
        End If
    End Function

    Private Sub UpdateTotalCost(sender As System.Object, e As System.EventArgs) Handles tb_Quantity.TextChanged, tb_UnitPrice.TextChanged
        tb_TotalCost.Text = GetTotalCost().ToString()
    End Sub


#Region "Input validation"


    Private Sub cmb_MaterialGrade_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles cmb_MaterialGrade.Validating
        Dim inputSpecification As New NotNullableComboBoxValidatingSpecification(Of Gatunek)
        _inputValidator.ValidateComboBox(cmb_MaterialGrade, e, lbl_MaterialGradeError, inputSpecification)
    End Sub

    Private Sub tb_Diameter_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles tb_Diameter.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(tb_Diameter, e, lbl_DiameterError, notNullableTextInputValidatingSpecification.And(numericPositiveInputValidatingSpecification))
    End Sub

    Private Sub tb_DiameterToleranceMinus_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles tb_DiameterToleranceMinus.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        _inputValidator.ValidateTextBox(tb_DiameterToleranceMinus, e, lbl_DiameterToleranceMinusError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification))
    End Sub

    Private Sub tb_DiameterTolerancePlus_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles tb_DiameterTolerancePlus.Validating

        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        '_inputValidator.ValidateTextBox(tb_DiameterToleranceMinus, e, lbl_DiameterToleranceMinusError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification))
        _inputValidator.ValidateTextBox(tb_DiameterTolerancePlus, e, lbl_DiameterTolerancePlusError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification))
        'If Not e.Cancel Then
        '    Dim diameterTolerancePlusValidatingSpecification As New DiameterTolerancePlusValidatingSpecification(Decimal.Parse(tb_DiameterToleranceMinus.Text.Trim()))

        'End If
    End Sub

    Private Sub tb_EnduranceMin_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles tb_EnduranceMin.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(tb_EnduranceMin, e, lbl_EnduranceMinError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification).And(numericPositiveInputValidatingSpecification))
    End Sub

    Private Sub tb_EnduranceMax_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles tb_EnduranceMax.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(tb_EnduranceMin, e, lbl_EnduranceMinError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification).And(numericPositiveInputValidatingSpecification))

        If Not e.Cancel Then
            Dim enduranceMaxValidatingSpecification As New EnduranceMaxValidatingSpecification(Decimal.Parse(tb_EnduranceMin.Text.Trim()))
            _inputValidator.ValidateTextBox(tb_EnduranceMax, e, lbl_EnduranceMaxError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification).And(numericPositiveInputValidatingSpecification).And(enduranceMaxValidatingSpecification))
        End If
    End Sub

    Private Sub tb_Quantity_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles tb_Quantity.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(tb_Quantity, e, lbl_QuantityError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification).And(numericPositiveInputValidatingSpecification))
    End Sub

    Private Sub cmb_MeasureUnit_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles cmb_MeasureUnit.Validating
        Dim inputSpecification As New NotNullableComboBoxValidatingSpecification(Of JednostkaMiary)
        _inputValidator.ValidateComboBox(cmb_MeasureUnit, e, lbl_MeasureUnitError, inputSpecification)
    End Sub

    Private Sub tb_UnitPrice_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles tb_UnitPrice.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(tb_UnitPrice, e, lbl_UnitPriceError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification).And(numericPositiveInputValidatingSpecification))
    End Sub


    Private Sub cmb_Material_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles cmb_MaterialGrade.Validated
        lbl_MaterialGradeError.Text = String.Empty
    End Sub

    Private Sub tb_Diameter_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles tb_Diameter.Validated
        lbl_DiameterError.Text = String.Empty
    End Sub

    Private Sub tb_DiameterToleranceMinus_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles tb_DiameterToleranceMinus.Validated
        lbl_DiameterToleranceMinusError.Text = String.Empty
    End Sub

    Private Sub tb_DiameterTolerancePlus_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles tb_DiameterTolerancePlus.Validated
        lbl_DiameterTolerancePlusError.Text = String.Empty
    End Sub

    Private Sub tb_EnduranceMin_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles tb_EnduranceMin.Validated
        lbl_EnduranceMinError.Text = String.Empty
    End Sub

    Private Sub tb_EnduranceMax_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles tb_EnduranceMax.Validated
        lbl_EnduranceMaxError.Text = String.Empty
    End Sub

    Private Sub tb_Quantity_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles tb_Quantity.Validated
        lbl_QuantityError.Text = String.Empty
    End Sub

    Private Sub cmb_MeasureUnit_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles cmb_MeasureUnit.Validated
        lbl_MeasureUnitError.Text = String.Empty
    End Sub

    Private Sub tb_UnitPrice_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles tb_UnitPrice.Validated
        lbl_UnitPriceError.Text = String.Empty

    End Sub


#End Region


    Private Sub btn_Accept_Click(sender As System.Object, e As System.EventArgs) Handles btn_Accept.Click
        Try
            If Not ValidateChildren() Then
                Throw New EntityDataInputException("Podane dane są nieprawidłowe." & vbNewLine &
                                                   "Popraw je i spróbuj ponownie.")
            End If

            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?", "Uwaga!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
            If confirmationDialogResult = Windows.Forms.DialogResult.Yes Then

                With WireOrderLine
                    .Diameter = Decimal.Parse(tb_Diameter.Text.Trim())
                    .DiameterToleranceMinus = Decimal.Parse(tb_DiameterToleranceMinus.Text.Trim())
                    .DiameterTolerancePlus = Decimal.Parse(tb_DiameterTolerancePlus.Text.Trim())
                    .EnduranceMax = Decimal.Parse(tb_EnduranceMax.Text.Trim())
                    .EnduranceMin = Decimal.Parse(tb_EnduranceMin.Text.Trim())
                    .MaterialGrade = CType(cmb_MaterialGrade.SelectedItem, Gatunek)
                    .MeasureUnit = CType(cmb_MeasureUnit.SelectedItem, JednostkaMiary)
                    .Packaging = If(IsNothing(cmb_Packaging.SelectedItem), Nothing, CType(cmb_Packaging.SelectedItem, Pakowanie))
                    .Quantity = Decimal.Parse(tb_Quantity.Text.Trim())
                    .UnitPrice = Decimal.Parse(tb_UnitPrice.Text.Trim())
                End With

                DialogResult = Windows.Forms.DialogResult.OK
            End If
        Catch ex As EntityDataInputException
            MessageBox.Show(ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub btn_Cancel_Click(sender As System.Object, e As System.EventArgs) Handles btn_Cancel.Click
        DialogResult = Windows.Forms.DialogResult.Cancel
    End Sub
End Class